QuickOPC User's Guide and Reference
Installed Examples - WindowsForms - SubscribeToMany

Demonstrates and measures performance with large number of subscribed OPC "Classic" (OPC-DA) items.

The form:

// $Header: $
// Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved.

// ReSharper disable NotNullMemberIsNotInitialized

using System.Diagnostics;
using System.Globalization;
using JetBrains.Annotations;
using OpcLabs.EasyOpc.DataAccess;
using System;
using System.Windows.Forms;
using OpcLabs.EasyOpc.DataAccess.OperationModel;

namespace SubscribeToMany
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int _changeCount;
        int _startTickCount;

        double GetElapsedTime()
        {
            return (Environment.TickCount - _startTickCount) / 1000.0;
        }
        
        private void startButton_Click(object sender, EventArgs e)
        {
            var numberOfItems = (int)numberOfItemsNumericUpDown.Value;

            startButton.Enabled = false;
            numberOfItemsNumericUpDown.Enabled = false;

            var argumentArray = new DAItemGroupArguments[numberOfItems];
            for (int i = 0; i < numberOfItems; i++)
            {
                var listViewItem = new ListViewItem();
                valuesListView.Items.Add(listViewItem);
                int copy = (i / 100) + 1;
                int phase = (i%100) + 1;
                string itemId = FormattableString.Invariant($"Simulation.Incrementing.Copy_{copy}.Phase_{phase}");
                argumentArray[i] = new DAItemGroupArguments("", "OPCLabs.KitServer.2", itemId, 50, listViewItem);
            }

            _changeCount = 0;
            _startTickCount = Environment.TickCount;
            timer1.Start();

            easyDAClient1.SubscribeMultipleItems(argumentArray);

        }

        private void easyDAClient1_ItemChanged(object sender, EasyDAItemChangedEventArgs e)
        {
            _changeCount++;

            var listViewItem = (ListViewItem)e.Arguments.State;
            Debug.Assert(listViewItem != null);

            string text;
            if (e.Exception is null)
            {
                Debug.Assert(e.Vtq != null);
                text = e.Vtq.DisplayValue();
            }
            else
                text = "*Error*";
            listViewItem.Text = text;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            double elapsedTime = GetElapsedTime();
            // ReSharper disable CompareOfFloatsByEqualityOperator
            if (elapsedTime == 0.0d)
            // ReSharper restore CompareOfFloatsByEqualityOperator
                return;

            int changeCount = _changeCount;
            double changesPerSecond = changeCount / elapsedTime;

            changeCountTextBox.Text = changeCount.ToString(CultureInfo.CurrentCulture);
            elapsedTimeTextBox.Text = $"{elapsedTime:0.0}";
            changesPerSecondTextBox.Text = $"{changesPerSecond:0.0}";
        }
    }
}
' $Header: $
' Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved.
Imports OpcLabs.EasyOpc.DataAccess
'using System.Linq;

Imports OpcLabs.EasyOpc.DataAccess.OperationModel ' ReSharper disable CheckNamespace
Namespace SubscribeToMany
    ' ReSharper restore CheckNamespace

    Partial Public Class Form1
        Inherits Form
        Public Sub New()
            InitializeComponent()
        End Sub

        Private _changeCount As Integer
        Private _startTickCount As Integer

        Private Function GetElapsedTime() As Double
            Return (Environment.TickCount - _startTickCount) / 1000.0
        End Function

        ' ReSharper disable InconsistentNaming
        Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startButton.Click
            ' ReSharper restore InconsistentNaming

            Dim numberOfItems As Integer = CInt(Fix(numberOfItemsNumericUpDown.Value))

            startButton.Enabled = False
            numberOfItemsNumericUpDown.Enabled = False

            Dim argumentArray = New DAItemGroupArguments(numberOfItems - 1) {}
            For i As Integer = 0 To numberOfItems - 1
                Dim listViewItem = New ListViewItem()
                valuesListView.Items.Add(listViewItem)
                Dim copy As Integer = (i \ 100) + 1
                Dim phase As Integer = i Mod 100
                Dim itemId As String = String.Format("Simulation.Incrementing.Copy_{0}.Phase_{1}", copy, phase)
                argumentArray(i) = New DAItemGroupArguments("", "OPCLabs.KitServer.2", itemId, 50, listViewItem)
            Next i

            _changeCount = 0
            _startTickCount = Environment.TickCount
            timer1.Start()

            easyDAClient1.SubscribeMultipleItems(argumentArray)

        End Sub

        ' ReSharper disable InconsistentNaming
        Private Sub easyDAClient1_ItemChanged(ByVal sender As Object, ByVal e As EasyDAItemChangedEventArgs) Handles easyDAClient1.ItemChanged
            ' ReSharper restore InconsistentNaming

            _changeCount += 1

            Dim listViewItem = CType(e.Arguments.State, ListViewItem)
            Dim itemText As String
            If e.Exception IsNot Nothing Then
                itemText = "*Error*"
            Else
                itemText = e.Vtq.DisplayValue()
            End If
            listViewItem.Text = itemText
        End Sub

        ' ReSharper disable InconsistentNaming
        Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles timer1.Tick
            ' ReSharper restore InconsistentNaming

            Dim elapsedTime As Double = GetElapsedTime()
            ' ReSharper disable CompareOfFloatsByEqualityOperator
            If elapsedTime = 0.0 Then
                ' ReSharper restore CompareOfFloatsByEqualityOperator
                Return
            End If

            Dim changeCount As Integer = _changeCount
            Dim changesPerSecond As Double = changeCount / elapsedTime

            changeCountTextBox.Text = changeCount.ToString()
            elapsedTimeTextBox.Text = String.Format("{0:0.0}", elapsedTime)
            changesPerSecondTextBox.Text = String.Format("{0:0.0}", changesPerSecond)
        End Sub
    End Class
End Namespace

 

See Also

Conceptual